//Headers from this project
#include "stroustrup_4.hpp"

//Headers from standard libraries
#include <iostream>
#include <cassert>
#include <limits>


stroustrup_4::stroustrup_4()
{
}

stroustrup_4::~stroustrup_4()
{
}

void stroustrup_4::test_boolalpha()
{
	std::cout << "Testing boolean with integer value assigned..." << std::endl;
	std::cout.setf(std::ios::boolalpha);
	bool b = 7;
	std::cout << "The value of b in boolean b = 7 expression is : "
		<<  b << std::endl;
	b = -7;
	std::cout << "The value of b in boolean b = -7 expression is : " << 
		b << std::endl;
	b = 0;
	std::cout << "The value of b in boolean b = 0 expression is : " <<
		b << std::endl;

	std::cout.unsetf(std::ios::boolalpha);
	std::cout << "Testing boolalpha..." << std::endl;
	std::cout << "The value of b in boolean b = 0 expression without boolalpha flag : " 
		<< b << std::endl;
}

void stroustrup_4::run()
{
	std::cout << "Testing Boolean Type ....." << std::endl;
	test_boolalpha();
	test_int_with_boolean_value();
	test_arithmetical_and_logical_expressions();
	std::cout << "Testing Char Type ....." << std::endl;
	test_char_type();
	std::cout << "Testing Integer Type ....." << std::endl;
	test_integer_type();
	std::cout << "Testing Floating Type ....." << std::endl;
	test_floating_type();
	std::cout << "Testing Sizes Of Types....." << std::endl;
	test_sizes_of_types();
	std::cout << "Testing of Void Type....." << std::endl;
	test_void_type();
}	


void stroustrup_4::test_int_with_boolean_value()
{
	std::cout << "Testing integer with boolean value assigned..." << std::endl;
	int i = true;
	std::cout << "The value of i in int i = true expression is : "
		<< i << std::endl;
	i = false;
	std::cout << "The value of i in int i = false expression is : "
		<< i << std::endl;
}

void stroustrup_4::test_arithmetical_and_logical_expressions()
{
	std::cout << "Testing Arithmetical and Logical Expressions..."<< std::endl;
	bool a = true;
	bool b = true;

	bool x = a + b;
	std::cout.setf(std::ios::boolalpha);
	std::cout << "The sum of two booleans is " << x << std::endl;
	bool y = a | b;
	std::cout << "The result of logical OR between two booleans is " 
								<< y << std::endl;
	int* k = 0;
	bool h = k;
	std::cout << h << std::endl;
	std::cout.setf(std::ios::boolalpha);
}

void stroustrup_4::test_char_type()
{
	std::cout << "Testing Char Type.... " << std::endl;
	unsigned char a = 'a';
	std::cout << "The value of " << a << " is " << int(a) << std::endl;
	char b = 48;
	std::cout << "The value of " << b << " is " << b << std::endl;
	unsigned char c = 'c';
	std::cout << "The value of " << c << " is " << int(c) << std::endl;
	unsigned char d = a + c;
	std::cout << "The value of 'a' + 'b' expression in case of,"
		" 'a' and 'b' are unsigned chars, is " << d << 
		"  which value is "<< int(d)  << " which belongs to [0, 255]"<< std::endl;
	assert(int(d) == (int(a) + int(c)));
	// Without signed is the same.
	signed char l = 'a';
	signed char k = 'c';
	signed char h = l + k;
	std::cout << "The value of 'a' + 'b' expression in case of "
		" 'a' and 'b' signed chars, is " << h <<  
		"  which value is " << int(h) << " which belongs to [-128, 127]" << std::endl;
}

void stroustrup_4::test_integer_type()
{
	unsigned short int i = -4;
	std::cout << "The negative value assigned to unsigned int accepted as"
		" unsigned int ranges from 0 to 65535(2^16)."
		" The first bit won't be viewed as bit of sign, so the result will be garbage :)"
		<< i << std::endl;
	std::cout << sizeof(short) << " <= " << sizeof(int)<< " <= " << sizeof(long) 
		<< std::endl;
	std::cout << sizeof(int) << " == " << sizeof(signed int)<< " == " 
		<< sizeof(unsigned int) << std::endl;
	short l = 3L;
	std::cout << "In the expression short l = 3L the size of l will be " << sizeof(l) << std::endl;
}

void stroustrup_4::test_floating_type()
{
	std::cout  << sizeof(float) << " <= " << sizeof(double)<< " <= " << sizeof(long double) 
		<< std::endl;
	long double l = 3L;
	std::cout << "In the expression long double = 3L the size of l will be " << sizeof(l) << std::endl;
}

void stroustrup_4::test_sizes_of_types()
{
        std::cout << "Here is the table of sizes of types " << std::endl;
        std::cout << "1 == " << sizeof(char) << " <= " << sizeof(short) 
                << " <= " << sizeof(int) << " <= " << sizeof(long) << std::endl;
        std::cout << "1 <= " << sizeof(bool) << " <= " << sizeof(long) 
                << std::endl; 
        std::cout <<  sizeof(char) << " <= " << sizeof(wchar_t) << " <= " 
                << sizeof(long) << std::endl;
        std::cout <<  sizeof(float) << " <= " << sizeof(double) << " <= " 
                << sizeof(long double) << std::endl;
        std::cout <<  sizeof(char) << " == " << sizeof(unsigned char) << " == " 
                << sizeof(signed char) << std::endl;
        std::cout <<  sizeof(short) << " == " << sizeof(unsigned short) <<
                " == " << sizeof(signed short) << std::endl;
        std::cout <<  sizeof(int) << " == " << sizeof(unsigned int) << " == " 
                << sizeof(signed int) << std::endl;
        std::cout <<  sizeof(long) << " == " << sizeof(unsigned long) <<
                " == " << sizeof(signed long) << std::endl;

        std::cout <<std::boolalpha;
        std::cout << "Minimum value for int: " << std::numeric_limits<int>::min() << std::endl;
        std::cout << "Maximum value for int: " << std::numeric_limits<int>::max() << std::endl;
        std::cout << "int is signed: " << std::numeric_limits<int>::is_signed << std::endl;
        std::cout << "Non-sign bits in int: " << std::numeric_limits<int>::digits << std::endl;
        std::cout << "int has infinity: " << std::numeric_limits<int>::has_infinity << std::endl;
}

void increase(void* data, int psize)
{
        if (psize == sizeof(char)) { 
                char* pchar; 
                pchar=(char*)data; 
                ++(*pchar);
        } else if (psize == sizeof(int)) { 
                int* pint; 
                pint=(int*)data;
                ++(*pint);
        }
}

void stroustrup_4::test_void_type()
{
        std::cout << "The declaring an object of void type is Compile Error.\n"
                << "void represents the absence of type, so void pointers"
                " are pointers that point to a value that has no type" 
                << std::endl;
        void* x;
        int i = 5;
        x = &i;
        std::cout << "The value of dereference of void* is  " << 
                *((int*)x) << std::endl;
        char a = 'x';
        int b = 1602;
        increase (&a, sizeof(a));
        increase (&b, sizeof(b));
        std::cout << a << ", " << b << std::endl;

}
